using System;
using System.Collections.Generic;
using System.Configuration;
using System.Xml;
using System.Xml.Serialization;

using Gonte.Xml.Serialization;

namespace Gonte.Configuration
{
    /// <summary>
    /// Allows a class library to have its own configuration file
    /// </summary>
    internal sealed class ClassLibraryConfiguration
    {
        #region Methods

        internal void Load(XmlDocument xmlDocument)
        {
            LoadSections(xmlDocument);
        }

        internal Object GetSection(string sectionName)
        {
            if (sections_.ContainsKey(sectionName))
            {
                return sections_[sectionName];
            }
            return null;
        } 

        #endregion

        #region Helpers

        private void LoadSections(XmlDocument xmlDocument)
        {
            sections_ = new Dictionary<string, Object>();
            XmlSerializer descriptorSerializer = new XmlSerializer(typeof(ClassLibraryConfigurationSectionDescriptor));

            XmlNodeList nodes = xmlDocument.GetElementsByTagName("section");
            foreach (XmlNode node in nodes)
            {
                ClassLibraryConfigurationSectionDescriptor sectionDescriptor = descriptorSerializer.Deserialize(new XmlNodeReader(node)) as ClassLibraryConfigurationSectionDescriptor;

                XmlNode sectionNode = xmlDocument.SelectSingleNode(string.Format("/configuration/{0}", sectionDescriptor.Name));
                if (sectionNode == null)
                {
                    throw new ConfigurationErrorsException(string.Format("Section of name: {0} must be declared in the configuration file.", sectionDescriptor.Name));
                }

                Type type = Type.GetType(sectionDescriptor.Type, true);
                ConfigurationSection section = Activator.CreateInstance(type) as ConfigurationSection;
                XmlObjectDeserializer deserializer = XmlObjectDeserializer.GetDeserializer(section);
                deserializer.Deserialize(sectionNode.InnerXml);

                sections_[sectionDescriptor.Name] = section;
            }
        } 

        #endregion

        #region Fields

        private Dictionary<string, Object> sections_; 

        #endregion
    }
}
